package com.tanhua.server.service;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.tanhua.commons.SoulConstants;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.*;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.*;
import com.tanhua.model.vo.QuestionVo;
import com.tanhua.model.vo.QuestionnaireVO;
import com.tanhua.model.vo.ReportVo;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class TestSoulService {

    @DubboReference
    private QuestionnaireApi questionnaireApi;
    @DubboReference
    private QuestionApi questionApi;
    @DubboReference
    private OptionApi optionApi;
    @DubboReference
    private ReportApi reportApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private DimensionApi dimensionApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public List<QuestionnaireVO> getQuestionnaire() {
        List<Questionnaire> questionnaires = questionnaireApi.getQuestionnaire();
        Map<ObjectId, List<QuestionVo>> questionMap = questionApi.getQuestions();

        //查询redis中用户可解锁的测试题等级
        int level = 1;
        Long userId = UserHolder.getUserId();
        String key = SoulConstants.QUESTIONNAIRE_LEVEL + userId;
        String levelStr = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotEmpty(levelStr)) {
            level = Integer.parseInt(levelStr);
        }

        int finalLevel = level;
        List<QuestionnaireVO> result = questionnaires.stream().map(questionnaire -> {
            List<QuestionVo> questions = questionMap.get(questionnaire.getId());
            QuestionnaireVO vo = QuestionnaireVO.init(questionnaire, questions);
            //查询是否解锁
            if (finalLevel >= questionnaire.getLevel()) {
                vo.setIsLock(0);
            } else {
                vo.setIsLock(1);
            }
            //设置报告id
            Report report = reportApi.getByQuestionnaireId(UserHolder.getUserId(), questionnaire.getId());
            if(null != report)
                vo.setReportId(report.getId().toHexString());
            return vo;
        }).collect(Collectors.toList());


        return result;
    }


    /**
     * 提交问卷
     * @param answers
     * @return
     */
    public String commitQuestionnaire(Map<String, List<Answer>> answers) {
        List<Answer> answerList = answers.get("answers");
        double score = optionApi.countScore(answerList);
        Answer answer = answerList.get(0);
        Questionnaire questionnaire = questionApi.findQuestionnaireId(answer.getQuestionId());

        //设置值
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.getById(userId);
        Report report = new Report();
        report.setUserId(userId);
        report.setQuestionnaireId(questionnaire.getId());
        report.setLevel(questionnaire.getLevel());
        report.setScore(score);
        report.setGender(userInfo.getGender());
        if(score < 21) {
            report.setConclusion(SoulConstants.OWL_CONCLUSION);
            report.setCover(SoulConstants.OWL_PIC);
        }else if(21 <= score && score <= 41) {
            report.setConclusion(SoulConstants.FOX_CONCLUSION);
            report.setCover(SoulConstants.FOX_PIC);
        }else if(score > 41 && score <= 55) {
            report.setConclusion(SoulConstants.RABBIT_CONCLUSION);
            report.setCover(SoulConstants.RABBIT_PIC);
        }else {
            report.setConclusion(SoulConstants.LION_CONCLUSION);
            report.setCover(SoulConstants.LION_PIC);
        }
        //保存报表
        String reportId = reportApi.save(report);
        List<ObjectId> optionIds = answerList.stream().map(answer1 -> new ObjectId(answer1.getOptionId())).collect(Collectors.toList());
        List<Double> scores = optionApi.findScore(optionIds);
        //保存维度
        dimensionApi.save(init(scores));
        //保存redis
        String key = SoulConstants.QUESTIONNAIRE_LEVEL + UserHolder.getUserId();
        redisTemplate.opsForValue().set(key, (questionnaire.getLevel()+1)+"");

        return reportId;
    }

    /**
     * 根基id获取问卷报告
     * @param reportId
     * @return
     */
    public ReportVo getReport(String reportId) {
        //获取问卷报告
        Report report = reportApi.get(reportId);
        Questionnaire questionnaire = questionnaireApi.getById(report.getQuestionnaireId());
        //获取评分相似的报告
        String gender = "woman".equals(report.getGender()) ? "man" : "woman";
        List<Report> reports = reportApi.getSimilarScore(UserHolder.getUserId(), report.getScore(), questionnaire.getLevel(), gender);
        List<SimilarYou> similarYous = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(reports)) {
            List<Long> userIds = reports.stream().map(Report::getUserId).collect(Collectors.toList());
            List<UserInfo> userInfos = userInfoApi.getBatchIds(userIds);
            similarYous = userInfos.stream().map(SimilarYou::init).collect(Collectors.toList());
        }
        List<Dimension> dimensions = dimensionApi.getByReportId(new ObjectId(reportId));
        return ReportVo.init(report, dimensions, similarYous);
    }

    /**
     * 维度算法
     * @param values
     * @return
     */
    private List<Dimension> init(List<Double> values) {
        Map<Double,Integer> map = new HashMap<>();
        for (Double value : values) {
            if (map.get(value) == null) {
                map.put(value, 1);
            }else {
                map.put(value, map.get(value) + 1);
            }
        }

        Integer s1 = map.get(1);
        Integer s2 = map.get(2);
        Integer s3 = map.get(3);
        Integer s4 = map.get(4);
        Integer s5 = map.get(5);
        Integer s6 = map.get(6);
        Integer s7 = map.get(7);

        Dimension dimension1 = new Dimension();
        dimension1.setKey("外向");
        int v1 = s1 * 4 + s2 * 5 + s3 * 6 + s4 * 7 + s5 * 8 + s6 * 9 + s7 * 10;
        dimension1.setValue(v1 + "");
        Dimension dimension2 = new Dimension();
        dimension2.setKey("判断");
        int v2 = s1 * 10 + s2 * 4 + s3 * 5 + s4 * 6 + s5 * 7 + s6 * 8 + s7 * 9;
        dimension2.setValue(v2 + "");
        Dimension dimension3 = new Dimension();
        dimension3.setKey("抽象");
        int v3 = s1 * 9 + s2 * 10 + s3 * 4 + s4 * 5 + s5 * 6 + s6 * 7 + s7 * 8;
        dimension3.setValue(v3 + "");
        Dimension dimension4 = new Dimension();
        dimension4.setKey("理性");
        int v4 = s1 * 8 + s2 * 9 + s3 * 10 + s4 * 4 + s5 * 5 + s6 * 6 + s7 * 7;
        dimension4.setValue(v4 + "");

        return Arrays.asList(dimension1, dimension2,dimension3,dimension4);
    }

}
